package com.photobook
{
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.DisplayObject;
	import flash.display.Loader;
	import flash.events.*;
	import flash.geom.Matrix;
	import flash.net.URLRequest;
	import flash.utils.ByteArray;
	import flash.utils.Timer;
	
	import mx.controls.listClasses.BaseListData;
	import mx.core.UIComponent;
	import mx.events.FlexEvent;
	
	

[Event(name="complete" , type="flash.events.Event")]
	public class AnimatedGifLoader extends UIComponent
	{
		//trace("생성자 호  ->" );
		public var autoPlay:Boolean = true;
		public var frames:Array;
		 
		private var _currentFrame:int;
		private var _isGif:Boolean;
		private var _smoothing:Boolean;  
		
		private var _loaded:Boolean = false;
		
		private var _maintainAspectRatio:Boolean = false;
		
		//silver
		public var _obj:Object;
		
		private var imageRatio:Number = 1;
		
		private var _filters:Array;
		
		private var loadCounter:int;

		private var decode:GIFDecoder;
		private var loader:Loader = new Loader();
		private var randerer:Loader = new Loader();
		
		private var bitmap:Bitmap = new Bitmap(null , "auto" , true);
		
		private var timer:Timer = new Timer(10, 0);
		
		private const LOADER_HEADER_SIZE:Number = 39;
		
		
		public function AnimatedGifLoader()
		{
			super();
			
			timer.addEventListener("timer" , timerHandler, false,0,true);			
			
			loader.contentLoaderInfo.addEventListener(Event.COMPLETE , completeHandler,false,0,true);
			randerer.contentLoaderInfo.addEventListener(Event.COMPLETE , imageLoadHandler,false,0,true);

			addChild(bitmap);
		}


		public function set timerCount(val:uint):void {
			timer.repeatCount = val;
		}



	    private var _data:Object;
	    public function get data():Object
	    {
	        return _data;
	    }

		



    /**
     *  @private
     */
    public function set data(value:Object):void
    {
        _data = value;
        source = listData ? listData.label : data;
           

       // dispatchEvent(new FlexEvent(FlexEvent.DATA_CHANGE));
    }
		

    private var _listData:BaseListData;		
    
    		
    public function get listData():BaseListData
    {
        return _listData;
    }

    /**
     *  @private
     */
    public function set listData(value:BaseListData):void
    {
        _listData = value;
    }		
		

		
		private function completeHandler(e:Event):void
		{
			dispatchEvent(new Event("complete"));	
			
			var gifByte:ByteArray = new ByteArray();
			gifByte.writeBytes(loader.contentLoaderInfo.bytes , LOADER_HEADER_SIZE , loader.contentLoaderInfo.bytesTotal);
			
			
			decode = new GIFDecoder(gifByte);
			
			_isGif = decode.isGif;

			loadCounter = 0;
			_currentFrame = 0;
			frames = [];

			if(decode.isGif) 
			{
				//trace("Gif Start  ->" );					
 				decode.parse();
				
				if (decode.numImages > 1) {
					imageRatio = decode.rectBounds[0].width / decode.rectBounds[0].width;
	
					if(this.width == 0 && this.height == 0)
					{
						this.width = decode.rectBounds[0].width;
						this.height = decode.rectBounds[0].height;
					}
	
					if(autoPlay)
					{
						timer.start();
					}
					
					_loaded = true;					
				} else {
					jpgLoader.contentLoaderInfo.addEventListener(Event.COMPLETE , jpgLoaderComplete,false,0,true);
					jpgLoader.loadBytes(loader.contentLoaderInfo.bytes);					
				}

			}
			else {
				jpgLoader.contentLoaderInfo.addEventListener(Event.COMPLETE , jpgLoaderComplete,false,0,true);
				jpgLoader.loadBytes(loader.contentLoaderInfo.bytes);									
			}


		}
		
		
		private function getBitmapData(ui:DisplayObject):BitmapData
		{
		        var rtn:BitmapData;
		                        
		        try
		        {
		                //rtn = new BitmapData(ui.width , ui.height , true , 0x00000000);
		                rtn = new BitmapData(ui.width , ui.height , true , 0x00000000);
		                //trace("getBitmapData : ComponentSize width:" + ui.width + " height:" + ui.height);
		        }
		        catch(e:Error)
		        {
		                //trace("ComponentSize width:" + ui.width + " height:" + ui.height);
		                //trace(e.message);
		                return null
		        }
		
		        rtn.draw(ui , new Matrix());
		        return rtn;
		} 


		
		private var jpgLoader:Loader = new Loader();
		
		private function jpgLoaderComplete(e:Event):void
		{
			bitmap.bitmapData = getBitmapData(jpgLoader.content);
			
			//bitmap.bitmapData = Bitmap(jpgLoader.content).bitmapData.clone();
			bitmap.smoothing = _smoothing;
			
			imageRatio = jpgLoader.width / jpgLoader.height;
			if(this.width == 0 && this.height == 0)
			{				
				this.width = jpgLoader.width;
				this.height = jpgLoader.height;
			}
			
			_loaded = true;
			
			
			// 강제로 이미지 줄임 
			bitmap.width = this.width; 
			bitmap.height = this.width * imageRatio;
			
			bitmap.x = (this.width - bitmap.width) / 2;
			bitmap.y = (this.height - bitmap.height) / 2;			
		}
		
		private function imageLoadHandler(e:Event):void
		{		
			frames.push(new Bitmap(Bitmap(randerer.content).bitmapData , "auto" , _smoothing));
			
			bitmap.bitmapData = Bitmap(randerer.content).bitmapData;
			bitmap.smoothing = _smoothing;
			dispatchEvent(new FlexEvent(FlexEvent.UPDATE_COMPLETE));

			loadCounter++;
		}
		
		private function timerHandler(e:Event):void
		{
			if (decode.numImages > 1) {
/* 			try { */
	 			if(loadCounter != decode.numImages)
					randerer.loadBytes(decode.getImageByteArray(currentFrame));
				else
				{
					bitmap.bitmapData = frames[currentFrame].bitmapData;
					bitmap.smoothing = _smoothing;
					dispatchEvent(new FlexEvent(FlexEvent.UPDATE_COMPLETE));
				}
				
				
				
				bitmap.filters = _filters;
	
				
				if(maintainAspectRatio)
				{
					bitmap.width = this.width;
					bitmap.height = this.width * imageRatio;
					
					bitmap.x = (this.width - bitmap.width) / 2;
					bitmap.y = (this.height - bitmap.height) / 2;
				}
				else
				{
					bitmap.width = this.width;
					bitmap.height = this.height;
				}
			
			
				timer.delay = decode.delays[_currentFrame];
				_currentFrame++;
				
				if(_currentFrame == decode.numImages) {
					_currentFrame = 0;
				}
				
/* 			} catch (error:Error) {				
				trace(e);
			} */	
			}			
			 
		}

		//=============================================
		//	source 
		//=============================================
		
		
		override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
		{
			//trace("updateDisplayList call");
			super.updateDisplayList(unscaledWidth , unscaledHeight);
			
			if(_loaded)
			{
				if(maintainAspectRatio)
				{
					bitmap.width = this.width;
					bitmap.height = this.width * imageRatio;
					
					bitmap.x = (this.width - bitmap.width) / 2;
					bitmap.y = (this.height - bitmap.height) / 2;
				}
				else
				{
					bitmap.width = this.width;
					bitmap.height = this.height;
				}	
			}
		}
		
		
		public var _url:Object;
		public function set source(value:Object):void
		{
			var url:Boolean = (value is String) ? true : false;
			_url = value;
			if(url)
			{
				loader.load(new URLRequest(value as String));
	            loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, IOErrorHandler,false,0,true); 				

			}
		}

        private function IOErrorHandler(event:IOErrorEvent) :void {
           // trace("ioErrorHandler: " + event);
        }
        
		public function get source():Object
		{
			return _url;
		}
		
		

		
		

		
		public function set currentFrame(value:int):void
		{
			randerer.loadBytes(decode.getImageByteArray(value));
			_currentFrame = value;
		}
		
		public function get currentFrame():int
		{
			return _currentFrame;
		}
		
		public function get isGif():Boolean
		{
			return _isGif;
		}
		
		public function set playing(value:Boolean):void
		{
			if(!_isGif) return;
			
			if(value)
				timer.start();
			else
				timer.stop();
		}
		
		public function get playing():Boolean
		{
			return timer.running;
		}
		
		public function get content():Bitmap
		{
			return bitmap;
		}
		
		public function set smoothing(value:Boolean):void
		{
			_smoothing = value;
		}
		
		public function get smoothing():Boolean
		{
			return _smoothing;
		}
		
		public function set maintainAspectRatio(value:Boolean):void
		{
			_maintainAspectRatio = value;
		}
		
		public function get maintainAspectRatio():Boolean
		{
			return _maintainAspectRatio;
		}
		
		override public function set filters(value:Array):void
		{
			_filters = value;
			
			bitmap.filters = _filters;
		}
		
		override public function get filters():Array
		{
			return _filters;
		}

		// 20080728 : 클릭시 이동할 url 담기 위해서 currentPage
		//silver 특정 값 추가 
		public function set etcObj(obj:Object):void
		{
			_obj = obj;
		}
		
		public function get etcObj():Object
		{
			return _obj;
		}
		
		
	}
}